home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 5 / BBS in a Box -Volume V (BBS in a Box) (April 1992).iso / Files / Prog / B-C / CTherm.cpt / CThermometer.p < prev    next >
Encoding:
Text File  |  1990-09-01  |  10.9 KB  |  307 lines  |  [TEXT/PJMM]

  1.     {****************************************************}
  2. {}
  3. {         CThermometer.p    }
  4. {        A Thermometer Class with two subclasses    }
  5. {            Class which displays progress of an operation via a filling rectangle or circle    }
  6. {        SUPERCLASS = CObject    }
  7. {        Copyright © 1990, Captain Mac Enterprises.  All rights reserved.    }
  8. {        You're free to modify this for your own needs. Please don't modify and redistribute    }
  9. {        8/23/90    }
  10. {}
  11. {****************************************************}
  12.  
  13. unit CThermometer;
  14. interface
  15.     uses
  16.         Script, MiniIntf;        {in a real project, replace MiniIntf with TCL}
  17.  
  18.     type
  19.         CThermometer = object(CObject)
  20. {internal instance variables}
  21.                 thermDialog: DialogPtr;        {dialog thermometer is drawn in}
  22.                 savePort: GrafPtr;            {used to save and restore port of caller}
  23.                 thermRect: Rect;                {rect of userItem in dialog, this eliminates calling GetDItem repeatedly}
  24.  
  25. {user defined instance variables}
  26.                 updateIncr: Integer;            {caller sets how often to update thermometer by percent, 1 - 100}
  27.                                         {numbers that divide into 100 evenly look best}
  28.                 thermPattern: Pattern;        {pattern to fill thermometer with}
  29.                 wantsTicks: Boolean;        {add tick marks to thermometer? not recommended for pies}
  30.  
  31. {methods}
  32.                 procedure IThermometer (msg: Str255; updatePercent: Integer; fillPattern: Pattern; wantTicks: Boolean);
  33.         {pass message to be displayed and increment to fill thermometer in}
  34.                 procedure ChangeMessage (newMsg: Str255);
  35.                 procedure Free;
  36.         {get rid of dialog}
  37.                 override;
  38.             end;
  39.  
  40.         CBarTherm = object(CThermometer)
  41.                 procedure IThermometer (msg: Str255; updatePercent: Integer; fillPattern: Pattern; wantTicks: Boolean);
  42.                 override;
  43.         {pass message to be displayed and increment to fill thermometer in}
  44.                 function AdjThermometer (percentToFill: Integer): Boolean;
  45.         {pass percent of thermometer to fill, 0 to 100}
  46.             end;
  47.  
  48.         CPieTherm = object(CThermometer)
  49.                 procedure IThermometer (msg: Str255; updatePercent: Integer; fillPattern: Pattern; wantTicks: Boolean);
  50.                 override;
  51.         {pass message to be displayed and increment to fill thermometer in}
  52.                 function AdjThermometer (percentToFill: Integer): Boolean;
  53.         {pass percent of thermometer to fill, 0 to 100}
  54.             end;
  55.  
  56. implementation
  57.  
  58.  
  59. {****************************************************}
  60. {}
  61. {        CenterWindow    }
  62. {        Center a window on the screen    }
  63. {}
  64. {****************************************************}
  65.     procedure CenterWindow (theWindow: WindowPtr);
  66.         var
  67.             h, v: Integer;
  68.     begin        {CenterWindow}
  69.         with theWindow^, portRect do
  70.             begin
  71.                 h := (screenBits.bounds.right - screenBits.bounds.left) div 2 - (right - left) div 2;
  72.                 v := GetMBarHeight div 2 + (screenBits.bounds.bottom - screenBits.bounds.top) div 2 - (bottom - top) div 2;
  73.             end;
  74.         MoveWindow(theWindow, h, v, True);
  75.     end;        {CenterWindow}
  76.  
  77.  
  78. {****************************************************}
  79. {}
  80. {        ProcessCancelled    }
  81. {        Return if command-period was pressed    }
  82. {}
  83. {****************************************************}
  84.     function ProcessCancelled: Boolean;
  85.         var
  86.             theEvent: EventRecord;
  87.             cmdDown: Boolean;
  88.             ch: Char;
  89.     begin        {ProcessCancelled}
  90.         if GetNextEvent(keyDownMask, theEvent) then        {look at keyDown events only}
  91.             with theEvent do
  92.                 begin
  93.                     cmdDown := BitAnd(modifiers, cmdKey) <> 0;        {is the command key down}
  94.                     ch := Chr(BitAnd(message, charCodeMask));        {get char code of key pressed & convert to char}
  95.                     ProcessCancelled := cmdDown & (ch = '.');        {and the answer is}
  96.                 end
  97.         else
  98.             ProcessCancelled := False;
  99.     end;        {ProcessCancelled}
  100.  
  101.  
  102. {****************************************************}
  103. {}
  104. {        CalcPoint    }
  105. {        Given an angle from 0 (degrees) and radius (pixels), returns point on a circle    }
  106. {}
  107. {****************************************************}
  108.     function CalcPoint (angle, radius: Integer): Point;        {angle from 0 and radius}
  109.         const
  110.             pi = 3.1415926535897932;
  111.     begin        {CalcPoint}
  112.         CalcPoint.h := Round(radius * Sin(angle / 360.0 * 2.0 * pi));
  113.         CalcPoint.v := Round(radius * Cos(angle / 360.0 * 2.0 * pi));
  114.     end;        {CalcPoint}
  115.  
  116.  
  117. {****************************************************}
  118. {}
  119. {        CThermometer.IThermometer    }
  120. {        Initialize a CThermometer object    }
  121. {}
  122. {****************************************************}
  123.     procedure CThermometer.IThermometer (msg: Str255; updatePercent: Integer; fillPattern: Pattern; wantTicks: Boolean);
  124.     begin        {CThermometer.IThermometer}
  125.         thermDialog := nil;
  126.         if (updatePercent > 0) & (updatePercent <= 100) then
  127.             updateIncr := updatePercent        {init updateIncr instance variable}
  128.         else
  129.             updateIncr := 5;        {if updatePercent not 1 - 100 then default to 5}
  130.         thermPattern := fillPattern;
  131.         wantsTicks := wantTicks;
  132.     end;        {CThermometer.IThermometer}
  133.  
  134.  
  135. {****************************************************}
  136. {}
  137. {        CThermometer.ChangeMessage    }
  138. {        Changes a CThermometer message    }
  139. {}
  140. {****************************************************}
  141.     procedure CThermometer.ChangeMessage (newMsg: Str255);
  142.         var
  143.             textRect: Rect;
  144.     begin
  145.         GetPort(savePort);
  146.         SetPort(thermDialog);
  147.         SetRect(textRect, 52, 14, 324, 65);
  148.         FrameRect(textRect);
  149.         TextBox(Pointer(Ord(@newMsg) + 1), Length(newMsg), textRect, teJustLeft);
  150.         SetPort(savePort);
  151.     end;
  152.  
  153.  
  154. {****************************************************}
  155. {}
  156. {        CThermometer.Free    }
  157. {        Dispose of CThermometer stuff    }
  158. {}
  159. {****************************************************}
  160.     procedure CThermometer.Free;
  161.     begin        {CThermometer.Free}
  162.         if thermDialog <> nil then        {make sure dialog existed before disposing of it}
  163.             DisposDialog(thermDialog);        {trash the dialog no longer needed}
  164.         inherited Free;        {let CObject clean up memory used by object itself}
  165.     end;        {CThermometer.Free}
  166.  
  167.  
  168. {****************************************************}
  169. {}
  170. {        CBarTherm.IThermometer    }
  171. {        Initialize a CBarTherm object    }
  172. {}
  173. {****************************************************}
  174.     procedure CBarTherm.IThermometer (msg: Str255; updatePercent: Integer; fillPattern: Pattern; wantTicks: Boolean);
  175.         var
  176.             dlogRect: Rect;
  177.             lowStr, highStr: Str255;
  178.             span, ticksCount, i, h: Longint;
  179.     begin        {CBarTherm.IThermometer}
  180.         GetPort(savePort);
  181.         inherited IThermometer(msg, updatePercent, fillPattern, wantTicks);
  182.         SetRect(dlogRect, 10, 32, 394, 148);
  183.         thermDialog := NewDialog(nil, dlogRect, '', False, 1, WindowPtr(-1), False, 0, nil);
  184.         SetPort(thermDialog);
  185.         CenterWindow(thermDialog);
  186.         ShowWindow(thermDialog);        {show the dialog}
  187.         SetRect(dlogRect, 52, 14, 324, 65);
  188.         TextBox(Pointer(Ord(@msg) + 1), Length(msg), dlogRect, teJustLeft);
  189.         SetRect(thermRect, 52, 78, 324, 94);
  190.         DrawDialog(thermDialog);        {draw the dialog}
  191.         FrameRect(thermRect);        {frame the userItem}
  192.  
  193.         if wantsTicks then        {caller wants tick marks displayed}
  194.             begin
  195.                 span := thermRect.right - thermRect.left;        {pixel span of thermometer}
  196.                 ticksCount := Trunc(100 / updateIncr) + 1;        {how many tick marks are needed}
  197.                 h := 0;        {offset between tick marks}
  198.                 for i := 1 to ticksCount do
  199.                     begin
  200.                         MoveTo(thermRect.left + h, thermRect.bottom);        {make a tick mark}
  201.                         LineTo(thermRect.left + h, thermRect.bottom + 2);
  202.                         h := (i * updateIncr * span div 100) - 1;        {calculate next offset}
  203.                     end;        {for i}
  204.             end;        {if wantsTicks}
  205.  
  206.         InsetRect(thermRect, 1, 1);        {inset rect 1 pixel so fill pattern does not erase frame}
  207.         lowStr := '0%';        {thermometer labels}
  208.         highStr := '100%';
  209.         MoveTo(thermRect.left, thermRect.top - 4);        {draw scale}
  210.         DrawString(lowStr);
  211.         MoveTo(thermRect.right - StringWidth(highStr), thermRect.top - 4);
  212.         DrawString(highStr);
  213.         SetPort(savePort);
  214.     end;        {CBarTherm.IThermometer}
  215.  
  216.  
  217. {****************************************************}
  218. {}
  219. {        CBarTherm.AdjThermometer    }
  220. {        Adjust a CBarTherm object    }
  221. {        Returns True if Command-period was pressed    }
  222. {}
  223. {****************************************************}
  224.     function CBarTherm.AdjThermometer (percentToFill: Integer): Boolean;
  225.     begin        {CBarTherm.AdjThermometer}
  226.         if percentToFill mod updateIncr = 0 then        {only fill therm at caller specified increment}
  227.             begin
  228.                 GetPort(savePort);
  229.                 SetPort(thermDialog);
  230.                 with thermRect do
  231.                     FillRect(top, left, bottom, (right - left) * percentToFill div 100 + left, thermPattern);        {fill the thermometer}
  232.                 SetPort(savePort);
  233.             end;
  234.         AdjThermometer := ProcessCancelled;        {return whether user pressed command-period}
  235.     end;        {CBarTherm.AdjThermometer}
  236.  
  237.  
  238. {****************************************************}
  239. {}
  240. {        CPieTherm.IThermometer    }
  241. {        Initialize a CPieTherm object    }
  242. {}
  243. {****************************************************}
  244.     procedure CPieTherm.IThermometer (msg: Str255; updatePercent: Integer; fillPattern: Pattern; wantTicks: Boolean);
  245.         var
  246.             ticksCount, radius, i: Integer;
  247.             dlogRect: Rect;
  248.             p1, p2, centerOfRect: Point;
  249.             tempPict: PicHandle;
  250.     begin        {CPieTherm.IThermometer}
  251.         GetPort(savePort);
  252.         inherited IThermometer(msg, updatePercent, fillPattern, wantTicks);
  253.         SetRect(dlogRect, 10, 32, 394, 248);
  254.         thermDialog := NewDialog(nil, dlogRect, '', False, 1, WindowPtr(-1), False, 0, nil);
  255.         SetPort(thermDialog);
  256.         CenterWindow(thermDialog);
  257.         ShowWindow(thermDialog);        {show the dialog}
  258.         SetRect(dlogRect, 52, 14, 324, 65);
  259.         TextBox(Pointer(Ord(@msg) + 1), Length(msg), dlogRect, teJustLeft);
  260.         SetRect(thermRect, 132, 78, 254, 200);
  261.         DrawDialog(thermDialog);        {draw the dialog}
  262.         tempPict := OpenPicture(thermDialog^.portRect);        {do drawing to picture, tick marks are slow}
  263.         FrameOval(thermRect);        {frame the userItem}
  264.  
  265.         if wantsTicks then        {caller wants tick marks displayed}
  266.             begin
  267.                 ticksCount := Trunc(100 / updateIncr);        {how many tick marks are needed}
  268.                 with thermRect do        {get the center of the rect}
  269.                     SetPt(centerOfRect, (right - left) div 2 + left, (bottom - top) div 2 + top);
  270.                 radius := (thermRect.right - thermRect.left) div 2;        {get the radius of the pie}
  271.                 for i := 0 to ticksCount do
  272.                     begin
  273.                         p1 := CalcPoint(updateIncr * i * 36 div 10, radius);        {get x,y point on pie}
  274.                         p2 := CalcPoint(updateIncr * i * 36 div 10, radius + 5);        {get x,y point on pie + extra}
  275.                         MoveTo(centerOfRect.h + p1.h, centerOfRect.v - p1.v);        {make a tick mark}
  276.                         LineTo(centerOfRect.h + p2.h, centerOfRect.v - p2.v);
  277.                     end;        {for i}
  278.             end;        {if wantsTicks}
  279.         ClosePicture;
  280.         DrawPicture(tempPict, thermDialog^.portRect);
  281.         KillPicture(tempPict);
  282.         InsetRect(thermRect, 1, 1);        {inset rect 1 pixel so fill pattern does not erase frame}
  283.         SetPort(savePort);
  284.     end;        {CPieTherm.IThermometer}
  285.  
  286.  
  287. {****************************************************}
  288. {}
  289. {        CPieTherm.AdjThermometer    }
  290. {        Adjust a CPieTherm object    }
  291. {        Returns True if Command-period was pressed    }
  292. {}
  293. {****************************************************}
  294.     function CPieTherm.AdjThermometer (percentToFill: Integer): Boolean;
  295.     begin        {CPieTherm.AdjThermometer}
  296.         if percentToFill mod updateIncr = 0 then        {only fill therm at caller specified increment}
  297.             begin
  298.                 GetPort(savePort);
  299.                 SetPort(thermDialog);
  300.                 with thermRect do
  301.                     FillArc(thermRect, 0, percentToFill * 36 div 10, thermPattern);        {fill the thermometer}
  302.                 SetPort(savePort);
  303.             end;
  304.         AdjThermometer := ProcessCancelled;        {return whether user pressed command-period}
  305.     end;        {CPieTherm.AdjThermometer}
  306.  
  307. end.        {CThermometer}